package com.softWang.common.handler;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.softWang.common.aop.annotation.DesensitizeCommon;

import java.io.IOException;

/**
 * 脱敏序列化器
 *
 * 实现 JSON 返回数据时，使用 {@link DesensitizeCommon} 脱敏注解的字段，进行脱敏处理。
 */
public class DesensitizeCommonSerializer extends StdSerializer<String> implements ContextualSerializer {

    private DesensitizeCommon annotation;
    protected DesensitizeCommonSerializer() {
        super(String.class);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) {
        this.annotation = beanProperty.getAnnotation(DesensitizeCommon.class);
        return this;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
        if (value == null || value.isEmpty()) {
            gen.writeNull();
            return;
        }
        if(this.annotation != null){
            // 2. 执行脱敏
            int prefixKeep = this.annotation.prefixKeep();
            int suffixKeep = this.annotation.suffixKeep();
            String replacer = this.annotation.replacer();
            int length = value.length();

            // 情况一：原始字符串长度小于等于保留长度，则原始字符串全部替换
            if (prefixKeep >= length || suffixKeep >= length) {
                value = buildReplacerByLength(replacer, length);
            }

            // 情况二：原始字符串长度小于等于前后缀保留字符串长度，则原始字符串全部替换
            if ((prefixKeep + suffixKeep) >= length) {
                value =  value.substring(0, prefixKeep) +
                        buildReplacerByLength(replacer, length-prefixKeep);
            }

            // 情况三：原始字符串长度大于前后缀保留字符串长度，则替换中间字符串
            int interval = length - prefixKeep - suffixKeep;
            value = value.substring(0, prefixKeep) +
                    buildReplacerByLength(replacer, interval) +
                    value.substring(prefixKeep + interval);
        }
        gen.writeString(value);
    }

    /**
     * 根据长度循环构建替换符
     *
     * @param replacer 替换符
     * @param length   长度
     * @return 构建后的替换符
     */
    private String buildReplacerByLength(String replacer, int length) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append(replacer);
        }
        return builder.toString();
    }

}